package com.kantboot.security.util;

import com.alibaba.fastjson2.JSON;
import com.kantboot.security.domain.entity.SecurityRequest;
import com.kantboot.security.dto.SecurityRequestDTO;
import com.kantboot.util.common.exception.BaseException;
import com.kantboot.util.common.http.HttpRequestHeaderUtil;
import com.kantboot.util.common.rsa.RSAUtil;
import lombok.extern.slf4j.Slf4j;

import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * 安全请求工具类
 * @author 方某方
 */
@Slf4j
public class SecurityRequestUtil {

    /**
     * 给SecurityRequest生成公钥和私钥
     *
     * @param securityRequest 安全请求实体
     */
    public static void generateKey(SecurityRequest securityRequest) {
        try {
            Map<String, String> keyMap = RSAUtil.initKeyPair();
            // 设置公钥
            securityRequest.setPublicKey(keyMap.get(RSAUtil.PUBLIC_KEY_STR));
            // 设置私钥
            securityRequest.setPrivateKey(keyMap.get(RSAUtil.PRIVATE_KEY_STR));
        } catch (Exception e) {
            throw BaseException.of("generateKeyError", "生成公钥私钥失败");
        }
    }

    /**
     * 根据SecurityRequest生成常规信息
     * 生成ip、User-agent、token、过期时间等信息
     *
     * @param securityRequest       安全请求实体
     * @param httpRequestHeaderUtil 请求头工具类
     */
    public static void generateCommonInfo(SecurityRequest securityRequest, HttpRequestHeaderUtil httpRequestHeaderUtil) {
        // 获取请求头中的User-agent
        String userAgent = httpRequestHeaderUtil.getUserAgent();
        // 获取ip
        String ip = httpRequestHeaderUtil.getIp();
        // 获取token
        String token = httpRequestHeaderUtil.getToken();
        // 设置最后的ip地址
        securityRequest.setLastIp(ip);
        // 设置ip集合
        securityRequest.setIpListStr(JSON.toJSONString(List.of(ip)));
        // 设置User-agent
        securityRequest.setUserAgent(userAgent);
        // 设置token
        securityRequest.setToken(token);
        // 设置过期时间
        securityRequest.setGmtExpire(new Date(System.currentTimeMillis() + 1000 * 60 * 60 * 24 * 7));
    }

    /**
     * 转发前的校验
     * @param securityRequest 安全请求
     * @param httpRequestHeaderUtil 请求头工具类
     */
    public static void checkBeforeForward(SecurityRequestDTO dto, SecurityRequest securityRequest, HttpRequestHeaderUtil httpRequestHeaderUtil) {
        if (securityRequest == null) {
            throw BaseException.of("securityRequestIsNull", "安全请求为空");
        }
//        if (securityRequest.getGmtExpire().before(new Date())) {
//            throw BaseException.of("securityRequestIsExpired", "安全请求已过期");
//        }
//        // 判断是否为同一ip，如果不是，且超过4次，则提示安全风险
//        if (!securityRequest.getIpListStr().contains(httpRequestHeaderUtil.getIp())) {
//            // 添加进ipListStr
//            List<String> ipList = JSON.parseArray(securityRequest.getIpListStr(), String.class);
//            // 如果换过多ip，则提示安全风险
//            if (ipList.size() > 4) {
//                // 提示安全风险
//                log.error("存在安全风险：{}，{}", "ip切换过多", JSON.toJSONString(ipList));
//                throw BaseException.of("securityRisk", "存在安全风险");
//            }
//        }
//        // 判断是否为同一token
//        if (!Objects.equals(securityRequest.getToken(), httpRequestHeaderUtil.getToken())) {
//            // 提示安全风险
//            log.error("存在安全风险：{}，{}", "token不一致", securityRequest.getToken()+"->"+httpRequestHeaderUtil.getToken());
//            throw BaseException.of("securityRisk", "存在安全风险");
//        }
//
//        // 判断是否为同一userAgent
//        if (!securityRequest.getUserAgent().equals(httpRequestHeaderUtil.getUserAgent())) {
//            // 提示安全风险
//            log.error("存在安全风险：{}，{}", "user-agent不一致", securityRequest.getUserAgent()+"->"+httpRequestHeaderUtil.getUserAgent());
//            throw BaseException.of("securityRisk", "存在安全风险");
//        }

        // 如果uri为空，直接抛出异常
        if (dto.getUri() == null) {
            throw BaseException.of("uriEmpty", "uri不能为空");
        }

    }

    /**
     * 补充DTO, 使其完整
     */
    public static void supplementDTO(SecurityRequestDTO dto) {
        // 如果method为空，直接赋值为POST
        if (dto.getMethod() == null) {
            dto.setMethod("POST");
        }
    }

    /**
     * 解密body
     */
    public static String decryptBody(String body, String privateKey) {
        // 如果body为空，直接赋值
        if (body == null) {
            body = "{}";
        }
        try {
            return RSAUtil.decryptByPrivateKey(body, privateKey);
        } catch (Exception e) {
            // 告知客户端，解析数据失败
            throw BaseException.of("decryptError", "解析数据失败");
        }
    }

}
